﻿/*迷宫的头文件，定义迷宫类、轨迹类、迷宫节点类、以及轨迹节点类；
*/

#ifndef MAZE_H
#define MAZE_H

#include <vector>

using namespace std;

namespace liandan{

const double infinateDouble = 9999.00;
const double exploreRate = 1.0 / 30.0;

class Maze;

class TrackNode{
public:
	int cellRow;
	int cellColumn;
	double time;

	//输入另一个轨迹节点，获取其相对于此节点的位置；
	//0：不相邻；
	//1：左；
	//2：上；
	//3：右；
	//4：下；
	int getRelitivePosition(TrackNode);

	//输入前后轨迹节点，获取此节点的转弯状况；
	//1：直行；
	//2：左转；
	//3：右转；
	//4：掉头；
	//0：非法；
	int getTurnState(TrackNode previous, TrackNode next);

	//输入另一轨迹节点，获取两节点间距离（非直线距离）；
	int getDistance(TrackNode anotherNode);
};

class Track{
	friend class Maze;

public:
	vector<TrackNode>trackData;
	int height;
	int width;
	int startColumn;
	int startRow;
	int endColumn;
	int endRow;

	friend class Maze;

	//基本上啥都没有的构造器；
	Track(int height, int width);

	//完整版构造器；
	Track(vector<TrackNode>, Maze);

	void setEndpoint(int startRow, int startColumn, int endRow, int endColumn);

	double getEvaluatedTime(double idealTime, double cornerRate, double UTurnRate);
	//Use this function to return the evaluated time;
	//cornerRate: time spend at corner divided by time spend at straight;

	Maze drawMaze(Maze);
	//基于路径画出一个新的迷宫，注意长宽要保持一致
	//After exploration, use this function to draw one maze;

	double getCoverage();
	//轨迹的迷宫覆盖率
	//Get the coverage during an explore;
	//Goal: the nearer to 1, the better;

	double getRepetationRate();
	//轨迹的路线重复率
	//Just get the repetation rate of the track, nothing more;

	int getCircleLength();
	//轨迹的环形路径长度
	//Get the worthless lengh the car moves;

	double getIdleTime(double idealTime, double cornerRate, double UTurnRate);
	//原地停留时间
	//Get the time spend on staying;
	//cornerRate: time spend at corner divided by time spend at straight;

	double getVarietyOfAlternation(Maze);
	//岔路选择多样性，为成功进行岔路选择的次数除以总的岔路选择的次数

	//判断此路径是否合法（相邻轨迹节点距离不大于1）；
	bool isLegal();

	//返回此轨迹实际所用时间；
	double getTotalTime();
};

class Cell {
public:
	// -1: unknown 0: blocked 1: unblocked
	Cell(){ up = -1; bottom = -1; left = -1; right = -1; height=infinateDouble;}

	int up;
	int bottom;
	int left;
	int right;
	double height;
	//注意这里的高度是经过转弯率计算后的结果

	//返回此单元格的状态：
	//0：不可接近
	//1：死路
	//2：通路
	//3：岔路
	//4：4面皆通
	int getState();
};

class Maze{

private:
	int width;
	int height;
	int startRow;
	int startColumn;
	int endRow;
	int endColumn;

public:

	friend class Track;

	void setEndpoint(int startRow, int startColumn, int endRow, int endColumn);

	vector< vector<Cell> > mazeData;
	//整个迷宫的左上角坐标为(0, 0);

	Maze(int height, int width, int startRow, int startColumn, int endRow, int endColumn);

	Maze(int height, int width, int startRow, int startColumn, int endRow, int endColumn, vector<Cell> mazeData);
	//One API function, transfer the data in vector<cell> into a Maze;

	void calculateHeight(double cornerRate);
	//计算所有单元格高度

	void legitimation();
	//合法化整个迷宫，使相邻两个单元格共享边状态保持一致;

	bool isLegal();
	//返回整个迷宫是否合法，若不合法则需要进行合法化;

	Track getBestTrack(double cornerRate);
	//理论最优路
	//This function is used to return the best track;
	//cornerRate: time spend at corner divided by time spend at straight;

	Track getBestTrackBasedOnExploration(double cornerRate, Track exploration);
	//基于探索的理论最优路
	//This function is used to return the best track based on the exploration;
	//cornerRate: time spend at corner divided by time spend at straight;

	//Reture the height, witch is the sum of cells' heights, of this maze;
	//获取整个迷宫高度（所有单元格高度之和）
	double getTotalHeight(double cornerRate);

	~Maze(void);
};

};

#endif	//	Maze.h